<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Acconeer API: Obstacle Detector</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">Acconeer API
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('obstacle.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Obstacle Detector </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The obstacle detector algorithm is based on the synthetic aperture radar (SAR) principle. The main goal of the detector is to find obstacles in front of the sensor and estimate their distance and angle. In an application where the sensor is installed on a robot (such as vacuum cleaners or lawn mowers), the object data can be used to issue movement commands to the robot to avoid and circumnavigate the found obstacles.</p>
<div class="image">
<img src="obstacle_intro.png" alt="obstacle_intro.png"/>
</div>
<p>Due to a half power beam width (HPBW) of 60 degrees along the H-plane of the sensor, detection of obstacles works best at 30 degrees from boresight angles. Note that strong reflectors, such as glass walls, usually can be seen up to almost 90 degrees from boresight. At the core of the detection algorithm is a fast Fourier transform (FFT), which is used to improve the signal-to-noise ratio (SNR) of obstacles in the vicinity of the radar sensor for extraction of angle alpha and distance d.</p>
<p>Four basic steps are repeated in this algorithm:</p>
<ul>
<li>Collecting radar sweeps from the IQ Service at a sweep frequency of fs</li>
<li>Perform FFT of N consecutive sweeps and estimate the power spectral density (PSD)</li>
<li>Perform peak detection on the PSD</li>
<li>Report distance d and estimate of angle alpha for found peaks (obstacles)</li>
</ul>
<p>For further understanding and information we recommend downloading our exploration tool, available from <a href="www.developer.acconeer.com">www.developer.acconeer.com</a>.</p>
<h1>Detecting Obstacles</h1>
<p>Detecting obstacles is a question of how well we can distinguish radar signals reflected off them from the noise floor of the sensor. While the sensor has very well-defined radar emission properties, radar scattering and reflection off obstacles depends strongly on their individual physical properties. Hence, the detection probability for obstacles is tied to the following key characteristics:</p>
<ul>
<li>distance of obstacle to radar sensor</li>
<li>angle of obstacle to radar sensor</li>
<li>reflectivity of obstacle at 60.5 GHz given by shape and material</li>
</ul>
<p>In particular, certain materials are known to only weakly reflect radar, while others are excellent reflectors. Untreated wood followed by treated wood and some plastic types fall in the first category and thus the maximum distance at which obstacles made from these materials can be detected is reduced. Metal, glass and water on the other hand are very good reflectors and can often be detected at quite far distances and large angles. Most other materials have reflectivity properties in between those two groups (most plastic types, tiles, granite) can be detected reasonably well at normal distances. Since radar emission is far outside the visible region of the EM-spectrum, color of materials does not matter.</p>
<p>It is important to understand, that radar signals may reflect off flat surfaces like a window or door in the same way visible light reflects off a mirror. Thus, if the obstacle has a large flat surface, which has a shallow angle with respect to the radar sensor normal, the obstacle might not be detected very well even if it is made from well reflecting material.</p>
<div class="image">
<img src="obstacle_detecting.png" alt="obstacle_detecting.png"/>
</div>
<p>Figure above show object with normal incidence resulting in good reflectivity and object with oblique incidence resulting in reduced detectability</p>
<h1>Understanding the Results</h1>
<p>The obstacle detector reports obstacles with 3 parameters, distance d, angle alpha and amplitude A. The amplitude is a measure of how much signal was reflected for that specific object; a value that is important for setting optimized thresholds for the obstacle detector.</p>
<div class="image">
<img src="obstacle_result.png" alt="obstacle_result.png"/>
</div>
<p>The distance is the actual distance of the obstacle to the radar sensor and the angle is the measured with respect to the direction of motion of the radar sensor. If you need the “normal” distance of the obstacle to the sensor, you can calculate it via the relation cos(alpha)d.</p>
<p>It is important to keep in mind that the reported angle is only reliable if the radar is moving with a known velocity and the object is at rest. For scenarios, where both, the sensor/robot and the object are moving, no definitive conclusion can be made about the objects true angle. The reason for this is that the angle is only inferred, i.e. calculated from the measured radial velocity of the object and not directly measured.</p>
<p>Since the obstacle’s radial velocity is obtained by performing an FFT over a given number of sweeps, it should be noted that there is a maximum velocity v that the detector can measure is</p>
<div class="image">
<img src="obstacle_result_2.png" alt="obstacle_result_2.png"/>
</div>
<p>where f is the sweep frequency and lambda is the radar wavelength (~5.0 mm). For objects that move at higher velocities, the reported object velocity, and therefore also angle, is incorrect. Thus, it is important to initialize the detector with settings that reflect the expected velocities for the desired application. For example, with a sweep frequency of 250 Hz, objects can be reliably detected at velocities below 30 cm/s. If one knows the radar is mounted on the robot so that object moving in one only direction can be observed, the maximum measurable velocity doubles to 60 cm/s.</p>
<p>The highest possible sweep frequency is depending on the MCU used and the range being scanned each sweep.</p>
<h2>Output from the Detector</h2>
<p>Detections are fetched from the obstacle detector.</p>
<div class="fragment"><div class="line">acc_obstacle_t obstacles[max_number_of_obstacles];</div><div class="line">acc_detector_obstacle_t obstacle_data;</div><div class="line"><span class="keywordtype">bool</span> status = <span class="keyword">true</span>;</div><div class="line"></div><div class="line">acc_detector_obstacle_result_info_t result_info;</div><div class="line"></div><div class="line">obstacle_data.obstacles = obstacles;</div><div class="line"></div><div class="line"><span class="keywordflow">do</span></div><div class="line">{</div><div class="line"> status = acc_detector_obstacle_get_next(handle, &amp;obstacle_data, &amp;result_info);</div><div class="line">}</div><div class="line"><span class="keywordflow">while</span> (status &amp;&amp; !result_info.data_available);</div></div><!-- fragment --><p>Detections will be available in obstacle_data when data_available is set. One obstacle is represented by an acc_detector_obstacle_t struct.</p>
<div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div><div class="line">{</div><div class="line"> <span class="keywordtype">float</span> radial_velocity;</div><div class="line"> <span class="keywordtype">float</span> distance;</div><div class="line"> <span class="keywordtype">float</span> amplitude;</div><div class="line">} acc_obstacle_t;</div></div><!-- fragment --><p>Amplitude is absolute value of complex IQ data and distance is the estimated distance in meters. Radial velocity is the radial velocity towards the sensor.</p>
<div class="image">
<img src="obstacle_output.png" alt="obstacle_output.png"/>
</div>
<p>Radial velocity is used to estimate the angle of an obstacle using</p>
<div class="image">
<img src="obstacle_output_2.png" alt="obstacle_output_2.png"/>
</div>
<h1>Configuring the Obstacle Detector</h1>
<h2>Create an Obstacle Configuration</h2>
<p>To start configuring the obstacle detector, an obstacle configuration must be created. The configuration will contain default parameter settings.</p>
<div class="fragment"><div class="line"><span class="comment">// Create an obstacle configuation</span></div><div class="line">acc_detector_obstacle_configuration_t configuration = acc_detector_obstacle_configuration_create();</div></div><!-- fragment --><h2>Setting General Settings</h2>
<p>General settings are similar to the other services and detectors. These settings determine how the ensor will generate data.</p>
<h3>Setting Range Start</h3>
<p>Configure how far from the sensor the detection range will start.</p>
<div class="fragment"><div class="line"><span class="comment">// Set range start to 0.12 meters</span></div><div class="line">acc_detector_obstacle_configuration_set_range_start(configuration, 0.12f);</div></div><!-- fragment --><h3>Setting Range Length</h3>
<p>Configure how long the detection range will be. Maximum length of detection range will depend on hardware computation power.</p>
<div class="fragment"><div class="line"><span class="comment">// Set range length to 0.3 meters</span></div><div class="line">acc_detector_obstacle_configuration_set_range_length(configuration, 0.3f);</div></div><!-- fragment --><h3>Setting Sensor</h3>
<p>When using a connector board with multiple sensors, configure which sensor should be used by the detector. If multiple sensors should be used, they must be configured separately.</p>
<div class="fragment"><div class="line"><span class="comment">// Set detector to use sensor 1</span></div><div class="line">acc_detector_obstacle_configuration_set_sensor(configuration, 1);</div></div><!-- fragment --><h3>Setting Gain</h3>
<p>Advanced users can control the receiver gain in the sensor. This may be useful for example in cases when measuring reflections from strong reflectors close to the sensor. The gain vale must be between 0.0 and 1.0, where 0.0 is the lowest gain and 1.0 is the highest gain.</p>
<div class="fragment"><div class="line"><span class="comment">// Set receiver gain to 0.7</span></div><div class="line">acc_detector_obstacle_configuration_set_gain(configuration, 0.7f);</div></div><!-- fragment --><h2>Setting Detector Specific Settings</h2>
<h3>Setting Max Number of Obstacles</h3>
<p>Configure how many obstacles the detector should look for. The number of obstacles found will affect the calculation time of the algorithm. One physical object may be returned as multiple obstacles, if the detector detects multiple reflections from the same object.</p>
<div class="fragment"><div class="line"><span class="comment">// Set max nubmer of obstacles to 1</span></div><div class="line">acc_detector_obstacle_configuration_set_max_number_of_obstacles(configuration, 1);</div></div><!-- fragment --><h3>Setting Max Speed</h3>
<p>This parameter is the speed limit of obstacles moving towards the sensor, i.e. the speed limit of the robot which sensor is mounted on. If moving faster than this, the detector will not be able to properly estimate the angle of the obstacle. The max speed parameter determines in what frequency the sensor will produce data.</p>
<div class="fragment"><div class="line"><span class="comment">// Set maxumim speed to 0.3 m/s</span></div><div class="line">acc_detector_obstacle_configuration_set_max_speed(configuration, 0.3f);</div></div><!-- fragment --> <h3>Setting Allow Reverse</h3>
<p>Disabling allow reverse will make it possible to have a higher max speed at a lower frequency. However, the detector will not be able to estimate angle of obstacles moving away from the sensor, i.e. if the sensor is mounted backwards. This setting is recommended if the sensors are mounted in the forward direction.</p>
<div class="fragment"><div class="line"><span class="comment">// Enable allow reverse</span></div><div class="line">acc_detector_obstacle_configuration_set_allow_reverse(configuration, <span class="keyword">true</span>);</div><div class="line"><span class="comment">// Disable allow reverse</span></div><div class="line">acc_detector_obstacle_configuration_set_allow_reverse(configuration, <span class="keyword">false</span>);</div></div><!-- fragment --><h3>Setting Downsample Scale</h3>
<p>Down sampling sensor data will increase the speed of the detection algorithm but may decrease the accuracy of distance and angle estimations.</p>
<div class="fragment"><div class="line"><span class="comment">// Set down sample scale to 8</span></div><div class="line">acc_detector_obstacle_configuration_set_downsample_scale(configuration, 8);</div></div><!-- fragment --><h3>Setting Edge to Peak Ratio</h3>
<p>To improve distance estimation, edge detection can be used. Edge to peak ratio controls the ratio between the peak amplitude and the edge amplitude. The edge amplitude will never be lower than the configured threshold.</p>
<div class="fragment"><div class="line"><span class="comment">// Set edge to peak ratio to 0.5</span></div><div class="line">acc_detector_obstacle_configuration_set_edge_to_peak_ratio(configuration, 0.5f);</div></div><!-- fragment --><h3>Setting Distance Offset</h3>
<p>Distance offset can be used to remove absolute offset error in distance estimation. Depending on sensor integration, an absolute error can be introduced to the distance estimation. The value will be subtracted from the estimated distance.</p>
<div class="fragment"><div class="line"><span class="comment">// Set distance offset to 0.01 meters</span></div><div class="line">acc_detector_obstacle_configuration_set_distance_offset(configuration, 0.01f);</div></div><!-- fragment --><h3>Setting Range End Over-scan</h3>
<p>The sensor will be set to sweep farther than the range. This will improve distance estimation close to the end of the range. If set to 0.03 meters, the sensor will sweep 0.03 meters beyond the end range but obstacle detection will still be done within the range.</p>
<div class="fragment"><div class="line"><span class="comment">// Set range end overscan to 0.03 meters</span></div><div class="line">acc_detector_obstacle_configuration_set_range_end_overscan(configuration, 0.03f);</div></div><!-- fragment --><h3>Setting Speed Filter High Pass</h3>
<p>Objects that have a radial speed towards the sensor lower than the highpass masking speed are not reported in the output. Set the high-pass masking for radial speed. The value represents the center of the gradient transition from zero amplitude to unchanged amplitude.</p>
<div class="fragment"><div class="line"><span class="comment">// Set highpass masking for radial speed to 0.01 m/s</span></div><div class="line">acc_detector_obstacle_configuration_set_speed_filter_highpass(configuration, 0.01f);</div></div><!-- fragment --><h2>Setting Background Estimation</h2>
<p>In background estimation and cancellation, the average signal power for all different speed indexes are recorded during the estimation and later subtracted from the signal.</p>
<p>The number of iterations that should be used for background estimation is configurable. Setting to zero will disable background estimation. A higher number of iterations will improve the background estimation.</p>
<div class="fragment"><div class="line"><span class="comment">// Set background estimation iterations to 10</span></div><div class="line">acc_detector_obstacle_configuration_set_background_estimation_iterations(configuration, 10);</div></div><!-- fragment --><h2>Setting Thresholds</h2>
<p>By configuring amplitude thresholds in the detector, it is possible to control the sensitivity of the detector. The thresholds should be set high enough to avoid getting false detections caused by noise, and low enough to not miss detections from small objects.</p>
<p>Close to the sensor, we have the static reflections from sensor casing and floor. Here we use the stationary threshold. It makes sure that stationary reflections are not reported as object detections.</p>
<p>We use the moving threshold for objects that moves towards or away from the sensor. We also use the moving threshold for objects that are further away from the sensor than distance_limit_far. Above this distance we assume that there is no contribution from stationary clutter caused by stationary objects. This makes it possible to detect objects at angles close to 90 degree if they are above distance_limit_far.</p>
<div class="fragment"><div class="line"><span class="comment">// Set amplitude thresholds</span></div><div class="line"><span class="keyword">const</span> acc_detector_obstacle_configuration_threshold_t thresholds =</div><div class="line">{</div><div class="line"> .stationary = 0.05f,</div><div class="line"> .moving = 0.02f,</div><div class="line"> .distance_limit_far = 0.25f</div><div class="line">};</div><div class="line">acc_detector_obstacle_configuration_set_thresholds(configuration, &amp;thresholds);</div></div><!-- fragment --><h1>Running Obstacle Detector</h1>
<h2>Creating and Activating the Detector</h2>
<p>When a configuration has been created and configured, the detector can be created. The configuration is validated, and memory needed by the detector is allocated during creation.</p>
<div class="fragment"><div class="line"><span class="comment">// Create an obstacle detector</span></div><div class="line">acc_detector_obstacle_handle_t handle = acc_detector_obstacle_create(configuration);</div><div class="line"><span class="keywordflow">if</span> (handle == NULL)</div><div class="line">{</div><div class="line"> <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><p>If detector creation returns NULL, an error has occurred. Otherwise the detector is ready to be activated.</p>
<div class="fragment"><div class="line"><span class="comment">// Activate an obstacle detector</span></div><div class="line"><span class="keywordtype">bool</span> status = acc_detector_obstacle_activate(handle);</div><div class="line"><span class="keywordflow">if</span> (!status)</div><div class="line">{</div><div class="line"> <span class="comment">/* Handle error and destroy obstacle detector */</span></div><div class="line">}</div></div><!-- fragment --><p>When the detector is activated it will be possible to start retrieving obstacles from the detector.</p>
<h2>Deactivating and Destroying the Detector</h2>
<p>To stop measurements, the detector must be deactivated.</p>
<div class="fragment"><div class="line"><span class="comment">// Deactivate an obstacle detector</span></div><div class="line"><span class="keywordtype">bool</span> status = acc_detector_obstacle_deactivate(handle);</div><div class="line"><span class="keywordflow">if</span> (!status)</div><div class="line">{</div><div class="line"> <span class="comment">/* Handle error and destroy obstacle detector */</span></div><div class="line">}</div></div><!-- fragment --><p>When the detector is stopped it can be destroyed to deallocate resources used by the detector.</p>
<div class="fragment"><div class="line"><span class="comment">// Destroy an obstacle detector</span></div><div class="line">acc_detector_obstacle_destory(&amp;handle);</div></div><!-- fragment --><h1>Tuning the Detector</h1>
<p>In order to achieve the best possible detector performance, it is important to conduct proper tuning of the detector for each application and hardware integration. There are several parameters that require tuning.</p>
<p>Thresholds for obstacle detection: if the amplitude of a found obstacle is below the threshold it will be discarded.</p>
<p>Background estimation: it is usually necessary to perform a background estimation as sensor enclosure, housing and surroundings of the sensor may generate reflections. The better the background estimation, the lower thresholds can be used.</p>
<p>For both threshold tuning and background estimation, Acconeer offers an easy-to-use Python based graphical user interface (available upon request).</p>
<h2>Background Estimation</h2>
<p>The detector offers a method for background estimation and cancellation. Measurements need to be performed with empty space in front of the sensor, but with full enclosure and housing.</p>
<p>For most cases, background estimation and cancellation is recommended, as it allows to set lower thresholds. With this method we estimate a full FFT background map. This map is subtracted from each FFT calculated, when the detector is running. For estimating a good background map, we recommend using 10 iterations, which means collecting 16 · 10 = 160 sweeps.</p>
<h2>Thresholds</h2>
<p>Setting too low thresholds will result in an increased number of false detections, while setting too high thresholds will result in reduced detector sensitivity and increased number of missed objects. Thus, finding the right thresholds is very important.</p>
<p>In the most basic setup, two different thresholds need to set, one for moving objects and one for static objects. The threshold for static objects is typically higher since enclosure, housing and surroundings are seen as static objects and need to be removed properly. Thresholds for moving objects, on the other hand, can be much lower.</p>
<p>For a more detailed explanation of the different thresholds that can be set we would like to refer you the available tuning tool and its documentation. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="md__home_ai_jenkins_workspace_sw-main_0D2_doc_user_guides_rss_user_guide_main.html">User guides</a></li>
    <li class="footer">Generated on Mon Dec 2 2019 09:40:46 for Acconeer API by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.13 </li>
  </ul>
</div>
</body>
</html>
